package com.tykboot.core.base.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.tykboot.core.base.BaseDao;
import com.tykboot.core.base.BaseService;
import com.tykboot.core.persistence.Criteria;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

/**
 * @author LiuYu
 */
public abstract class BaseServiceImpl<T> implements BaseService<T> {

    @Autowired
    private BaseDao<T, Object> baseDao;

    @PersistenceContext
    private EntityManager entityManager;

    @Override
    public T findById(Object id) {
        Optional<T> entity = baseDao.findById(id);
        return entity.isPresent() ? entity.get() : null;
    }

    @Override
    public T findOne(Criteria<T> criteria) {
        Optional<T> entity = baseDao.findOne(criteria);
        return entity.get();
    }

    @Override
    public <S> S findBySql(String sql, Class<S> clazz) {
        Query query = entityManager.createNativeQuery(sql, clazz);
        List list = query.getResultList();
        if (list != null && !list.isEmpty()) {
            Object object = list.get(0);
            return JSON.parseObject(JSON.toJSONString(object), clazz);
        }
        return null;
    }

    @Override
    public List<T> findAll() {
        return baseDao.findAll();
    }

    @Override
    public List<T> findAllByIds(Iterable<Object> ids) {
        return baseDao.findAllById(ids);
    }

    @Override
    public List<T> findAll(Example<T> example) {
        return baseDao.findAll(example);
    }

    @Override
    public List<T> findAll(Criteria<T> criteria) {
        return baseDao.findAll(criteria);
    }

    @Override
    public Page<T> findAll(Pageable pageable) {
        return baseDao.findAll(pageable);
    }

    @Override
    public Page<T> findAll(Example<T> example, Pageable pageable) {
        return baseDao.findAll(example, pageable);
    }

    @Override
    public Page<T> findAll(Criteria<T> criteria, Pageable pageable) {
        return baseDao.findAll(criteria, pageable);
    }

    @Override
    public <S> List<S> findAllBySql(String sql, Class<S> clazz) {
        Query query = entityManager.createNativeQuery(sql, clazz);
        List list = query.getResultList();
        if (list != null && !list.isEmpty()) {
            return JSONArray.parseArray(JSON.toJSONString(list), clazz);
        }
        return new ArrayList<>();
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void executeSql(String sql) {
        Query query = entityManager.createNativeQuery(sql);
        query.executeUpdate();
    }

    @Override
    public T save(T entity) {
        return baseDao.save(entity);
    }

    @Override
    public List<T> saveAll(Iterable<T> entities) {
        return baseDao.saveAll(entities);
    }

    @Override
    public void deleteById(Object id) {
        baseDao.deleteById(id);
    }

    @Override
    public void delete(T entity) {
        baseDao.delete(entity);
    }

    @Override
    public void deleteAll(Iterable<T> entities) {
        baseDao.deleteAll(entities);
    }

    @Override
    public void deleteAll() {
        baseDao.deleteAll();
    }

    @Override
    public boolean existsById(Object id) {
        return baseDao.existsById(id);
    }

    @Override
    public long count() {
        return baseDao.count();
    }

    @Override
    public long count(Criteria<T> criteria) {
        return baseDao.count(criteria);
    }
}
